package cn.wolfcode.proxyy;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.wolfcode.domain.SystemLog;
import cn.wolfcode.service.ISystemLogService;
import cn.wolfcode.util.IPUtil;
import cn.wolfcode.util.ParameterMapUtil;
import cn.wolfcode.util.RequiredPermission;
import cn.wolfcode.util.UserContext;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

@Component //把当前类注入到spring容器中
@Aspect    //把当前类标识为一个切面供容器读取
public class AopConfig {

    @Autowired
    private ISystemLogService systemLogService;
    /**
     * 指定切入点
     * 对贴有自定义注解@RequiredPermission的方法，进行切面
     */
    @Pointcut("@annotation(cn.wolfcode.util.RequiredPermission)")
    private void useMethod() {

    }

    /**
     * 对切入点进行增强
     */
    @Around(value = "useMethod()")
    public Object recordLog(ProceedingJoinPoint jp) throws Throwable {

        //1.获取用户行为日志(ip,username,operation,method,params,time,createdTime)
        //获取类的字节码对象，通过字节码对象获取方法信息
        Class<?> targetCls = jp.getTarget().getClass();
        //获取方法签名(通过此签名获取目标方法信息)
        MethodSignature ms = (MethodSignature) jp.getSignature();
        //获取目标方法上的注解指定的操作名称
        Method targetMethod =
                targetCls.getDeclaredMethod(
                        ms.getName(),
                        ms.getParameterTypes());
        RequiredPermission requiredLog =
                targetMethod.getAnnotation(RequiredPermission.class);
        String operation = requiredLog.expression();

        System.out.println("targetMethod=" + targetMethod);
        //获取目标方法名(目标类型+方法名)
        String targetClsName = targetCls.getName();
        String targetObjectMethodName = targetClsName + "." + ms.getName();
        //2.封装用户行为日志(SystemLog)
        SystemLog systemLog = new SystemLog();
        //获取请求参数
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Map<String, String[]> parameterMap = request.getParameterMap();
        ParameterMapUtil.getParameterMap(request);
        String prametr = JSON.toJSONString(parameterMap);
        systemLog.setPrameter(prametr);
        //设置ip
        systemLog.setIp(IPUtil.getIpAddr(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()));
        //记录用户
        systemLog.setUsername(UserContext.getCurrentUser().getUsername());
        //执行的方法
        systemLog.setOperation(operation);

        //执行的操作方法
        systemLog.setOperationMethod(targetObjectMethodName);

        //记录做操作的时间
        systemLog.setOperationTime(new Date());

        TimeInterval timer = DateUtil.timer();
        //执行处理方法（执行控制器中的方法）
        Object result = jp.proceed();
        long handlerTime = timer.interval();//花费毫秒数
        //记录处理时间
        systemLog.setHandlerTime(handlerTime);
        //处理结果信息
        systemLog.setResultMsg("无");
        //操作名称（员工新增/删除等）
        systemLog.setOperationPs(requiredLog.name());
        systemLogService.save(systemLog);
        //result是方法的返回值，直接return回去就会返回给springmvc处理
        return result;
    }


}